package com.huidu.bitrade.controller.businessAuth;

import static com.huidu.bitrade.constant.CertifiedBusinessStatus.*;
import static org.springframework.util.Assert.isTrue;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.huidu.bitrade.constant.*;
import com.huidu.bitrade.service.*;
import com.huidu.bitrade.vo.BusinessApplyVO;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.huidu.bitrade.controller.BaseController;
import com.huidu.bitrade.entity.BusinessAuthApply;
import com.huidu.bitrade.entity.BusinessCancelApply;
import com.huidu.bitrade.entity.DepositRecord;
import com.huidu.bitrade.entity.Member;
import com.huidu.bitrade.entity.MemberWallet;
import com.huidu.bitrade.entity.QBusinessCancelApply;
import com.huidu.bitrade.util.DateUtil;
import com.huidu.bitrade.util.MessageResult;
import com.huidu.bitrade.util.PredicateUtils;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.querydsl.core.types.dsl.BooleanExpression;

@RestController
@RequestMapping("business/cancel-apply")
public class BusinessCancelApplyController extends BaseController {
    private static Logger logger = LoggerFactory.getLogger(BusinessCancelApplyController.class);
    @Autowired
    private BusinessCancelApplyService businessCancelApplyService;
    @Autowired
    private DepositRecordService depositRecordService;
    @Autowired
    private BusinessAuthApplyService businessAuthApplyService;
    @Autowired
    private MemberWalletService memberWalletService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private LocaleMessageSourceService msService;
    @Autowired
    private MemberTransactionService memberTransactionService;

    @PostMapping("page-query")
    @RequiresPermissions("business:cancel-apply:page-query")
    public MessageResult pageQuery(
            PageModel pageModel,
            @RequestParam(value = "account", required = false) String account,
            @RequestParam(value = "status", required = false) CertifiedBusinessStatus status,
            @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") Date startDate,
            @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") Date endDate) {
        List<BooleanExpression> predicates = new ArrayList<>();
        if (!StringUtils.isEmpty(account)) {
            predicates.add(QBusinessCancelApply.businessCancelApply.member.username.like("%" + account + "%")
                    .or(QBusinessCancelApply.businessCancelApply.member.mobilePhone.like("%" + account + "%"))
                    .or(QBusinessCancelApply.businessCancelApply.member.email.like("%" + account + "%"))
                    .or(QBusinessCancelApply.businessCancelApply.member.realName.like("%" + account + "%")));
        }
        predicates.add(QBusinessCancelApply.businessCancelApply.status.in(CANCEL_AUTH, RETURN_FAILED, RETURN_SUCCESS));
        if (status != null) {
            predicates.add(QBusinessCancelApply.businessCancelApply.status.eq(status));
        }
        if (startDate != null) {
            predicates.add(QBusinessCancelApply.businessCancelApply.cancelApplyTime.goe(startDate));
        }
        if (endDate != null) {
            predicates.add(QBusinessCancelApply.businessCancelApply.cancelApplyTime.loe(endDate));
        }

        Page<BusinessCancelApply> page = businessCancelApplyService.findAll(PredicateUtils.getPredicate(predicates), pageModel);

        for (BusinessCancelApply businessCancelApply : page.getContent()) {
            DepositRecord depositRecord = depositRecordService.findOne(businessCancelApply.getDepositRecordId());
            businessCancelApply.setDepositRecord(depositRecord);
            Member member = businessCancelApply.getMember();
            if (member.getBusinessDepositStrategy() != null) {
                businessCancelApply.setMemberLevel(member.getBusinessDepositStrategy().getBusinessLevelEnum().getCnName());
            }else {
                MemberLevelEnum memberLevel = member.getMemberLevel();
                businessCancelApply.setMemberLevel(memberLevel.getCnName());
            }
        }
        return success(page);
    }

    /**
     * 取消商家认证 退保审核
     *
     * @param id
     * @param success 通过 : IS_TRUE
     * @param reason  审核不通过的理由
     * @return
     */
    @RequiresPermissions("business:cancel-apply:check")
    @PostMapping("check")
    @Transactional(rollbackFor = Exception.class)
    public MessageResult pass(
            @RequestParam(value = "id") Long id,
            @RequestParam(value = "success") BooleanEnum success,
            @RequestParam(value = "reason", defaultValue = "") String reason) {
        BusinessCancelApply businessCancelApply = businessCancelApplyService.findOne(id);
        //确认是待审状态
        isTrue(businessCancelApply.getStatus() == CANCEL_AUTH, "记录不是待审状态");
        Member member = businessCancelApply.getMember();
        isTrue(member.getCertifiedBusinessStatus() == CANCEL_AUTH, "商家不是待审状态");
        //查询用户最新已通过认证申请
        List<BusinessAuthApply> businessAuthApplyList = businessAuthApplyService.findByMemberAndCertifiedBusinessStatus(member, VERIFIED);
        if (businessAuthApplyList == null || businessAuthApplyList.isEmpty()) {
            return error("data exception,businessAuthApply not exist。。。。");
        }
        BusinessAuthApply businessAuthApply = businessAuthApplyList.get(0);
        //处理 取消申请 日志
        businessCancelApply.setHandleTime(DateUtil.getCurrentDate());
        businessCancelApply.setDepositRecordId(businessAuthApply.getDepositRecordId());
        businessCancelApply.setDetail(reason);
        //退保审核
        if (success == BooleanEnum.IS_TRUE) {
            //1.退保通过申请
            businessCancelApply.setStatus(RETURN_SUCCESS);
            businessCancelApplyService.save(businessCancelApply);
            //2.取消商家认证
            member.setCertifiedBusinessStatus(NOT_CERTIFIED);
            member.setMemberLevel(MemberLevelEnum.REALNAME);
            member.setBusinessDepositStrategy(null);//承兑保证金
            memberService.save(member);
            //3.认证商家缴纳记录 索回
            DepositRecord depositRecord = depositRecordService.findOne(businessAuthApply.getDepositRecordId());
            if (depositRecord != null && depositRecord.getStatus() == DepositStatusEnum.PAY) {
                depositRecord.setStatus(DepositStatusEnum.GET_BACK);
                depositRecordService.save(depositRecord);
                //4.返还认证商家保证金到余额
                MemberWallet memberWallet = memberWalletService.findByCoinUnitAndMemberId(depositRecord.getCoin().getUnit(), member.getId());
                memberWalletService.increaseBalance(memberWallet.getId(),depositRecord.getAmount());
                //5.保存交易流水
                memberTransactionService.saveBusinessMemberTransaction(depositRecord.getAmount(), TransactionType.MERCHANT_BAIL_RETURN, member.getId());
            }
            return MessageResult.success(msService.getMessage("PASS_THE_AUDIT"), reason);
        } else {
            //审核不通过，商家 维持已认证状态
            //member.setCertifiedBusinessStatus(RETURN_FAILED);
            member.setCertifiedBusinessStatus(VERIFIED);
            member.setMemberLevel(MemberLevelEnum.IDENTIFICATION);
            memberService.save(member);
            businessCancelApply.setStatus(RETURN_FAILED);
            businessCancelApplyService.save(businessCancelApply);
            return MessageResult.success(msService.getMessage("AUDIT_DOES_NOT_PASS"), reason);
        }
    }

    /**
     * @param id:businessCancelApply id
     * @return
     */

    @PostMapping("detail")
    @RequiresPermissions("business:cancel-apply:detail")
    public MessageResult detail(@RequestParam(value = "id") Long id) {
        BusinessCancelApply businessCancelApply = businessCancelApplyService.findOne(id);
        DepositRecord depositRecord = depositRecordService.findOne(businessCancelApply.getDepositRecordId());
        BusinessApplyVO vo = businessCancelApplyService.getBusinessOrderStatistics(businessCancelApply.getMember().getId());
        logger.info("会员订单信息:{}", vo);
        Map<String, Object> map2 = businessCancelApplyService.getBusinessAppealStatistics(businessCancelApply.getMember().getId());
        logger.info("会员申诉信息:{}", map2);
        Long advertiseNum = businessCancelApplyService.getAdvertiserNum(businessCancelApply.getMember().getId());
        logger.info("会员广告信息:{}", advertiseNum);
        Map<String, Object> map = new HashMap<>(map2);
        map.put("fee", vo.getFee());
        map.put("money", vo.getMoney());
        map.put("advertiseNum", advertiseNum);
        map.put("businessCancelApply", businessCancelApply);
        map.put("depositRecord", depositRecord);
        logger.info("会员退保相关信息:{}", map);
        Member member = businessCancelApply.getMember();
        if (member.getBusinessDepositStrategy() != null) {
            businessCancelApply.setMemberLevel(member.getBusinessDepositStrategy().getBusinessLevelEnum().getCnName());
        }else {
            MemberLevelEnum memberLevel = member.getMemberLevel();
            businessCancelApply.setMemberLevel(memberLevel.getCnName());
        }
        return success(map);
    }

    @PostMapping("get-search-status")
    public MessageResult getSearchStatus() {
        CertifiedBusinessStatus[] statuses = CertifiedBusinessStatus.values();
        List<Map> list = new ArrayList<>();
        for (CertifiedBusinessStatus status : statuses) {
            if (status.getOrdinal() < CertifiedBusinessStatus.CANCEL_AUTH.getOrdinal()) {
                continue;
            }
            Map map = new HashMap();
            map.put("name", status.getCnName());
            map.put("value", status.getOrdinal());
            list.add(map);
        }
        return success(list);
    }
}
